package com.campus.commons.utils.excel;

import com.campus.commons.entity.EveningSubject;
import com.campus.commons.utils.Tool;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class EasyPoiRead {
    /**
     * 读取多列的条件类
     */
   private static class ReadValues{
        Sheet sheet;
        int startRow;
        int endRow;
        int startCol;
        int endCol;
        public ReadValues(Sheet sheet, int startRow, int endRow, int startCol, int endCol) {
            this.sheet = sheet;
            this.startRow = startRow;
            this.endRow = endRow;
            this.startCol = startCol;
            this.endCol = endCol;
        }
    }
    //获取读取条件类
  public static  ReadValues getReadValues(Sheet sheet,int startRow,int endRow,int startCol,int endCol) {
        return new ReadValues(sheet,startRow,endRow,startCol,endCol);
    }

    /**
     * 简单的读
     * @param sheet 要读的页
     * @param readValues  要读的列
     * @param <T>
     * @return
     * @throws IOException
     */
   public static <T extends Workbook>  List<Map<String, Object>>  simpleRead(String filePath,int sheet,ReadValues readValues) throws IOException {
        Workbook workbook=getWorkbook(filePath);
        Sheet sheetAt = workbook.getSheetAt(sheet);
        return getValues(readValues);
    }

    /**
     * 简单的读取第一页的指定内容
     * @param readValues
     * @param <T>
     * @return
     * @throws IOException
     */
  public   static <T extends Workbook>  List<Map<String, Object>>  simpleRead(String filePath,ReadValues readValues) throws IOException {
     return simpleRead(filePath,0, readValues);
    }

    /**
     * 返回Workbook
     * @param filePath  绝对路径文件位置
     * @return
     * @throws IOException
     */
    public static <T extends Workbook> Workbook getWorkbook(String filePath) throws IOException {
        Workbook workbook;
        File file = new File(filePath);
        if (!file.exists()) {
            throw new RuntimeException("文件不存在");
        }
        InputStream in = new FileInputStream(file);
        String suffix = filePath.substring(filePath.lastIndexOf("."));
        switch (suffix) {
            case "xls":
                return    workbook = new HSSFWorkbook(in);
            case "xlsx":
                return   workbook = new XSSFWorkbook(in);
            default:
                throw new RuntimeException("该文件不是一个表格文件");
        }
    }

    /**
     * 传入一个流和文件名字,返回一个 workBook
     * @param in
     * @param fileName
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T extends Workbook> Workbook getWorkbook(InputStream in,String fileName) throws IOException {
        Workbook workbook;
        switch (fileName.substring(fileName.lastIndexOf(".")+1)) {
            case "xls":
                return    workbook = new HSSFWorkbook(in);
            case "xlsx":
                return   workbook = new XSSFWorkbook(in);
            default:
                throw new RuntimeException("该文件不是一个表格文件");
        }
    }

    /**
     * 获取指定的columns(列）
     * @param readValues
     * @return
     */
    public static List<Map<String, Object>> getValues(ReadValues readValues) {
       return getValues(readValues.sheet, readValues.startRow, readValues.endRow, readValues.startCol, readValues.endCol);
    }
    /** 用于读取页的指定列表，
     * 获取指定行的值 返回List每一项代表一行
     * @param sheet 页
     * @param startRow 开始行
     * @param endRow 结束行
     * @param startCol 开始的列
     * @param endCol  结束的列(包括这个列)
     * @return
     */
   public static List<Map<String, Object>> getValues(Sheet sheet,int startRow,int endRow,int startCol,int endCol) {
        List<Map<String, Object>> list = new ArrayList<>();
        for (int i = startRow; i <=endRow ; i++) {
            Row row = sheet.getRow(i);
            Map<String, Object> li = new HashMap<>();
            for (int j = startCol  ; j <=endCol ; j++) {
                Cell cell = row.getCell(j);
                Object value = getValue(cell);
                li.put("param" + j, value);
            }
            list.add(li);
        }
        return list;
    }


    /**
     * 通过一个列获取值
     * @param cell 列
     * @return 这个列的值
     */
    public static Object getValue(Cell cell) {
        return getValue(cell, false);
    }

    /** 这个方法遇到时间类型可能会处理的更好；
     * 通过一个列获取值
     * @param cell 列
     * @param isDate  是否确定是时间类型；
     * @return 这个列的值
     */
    public static Object getValue(Cell cell,boolean isDate) {
        //如果获取不到列return 空串
        if (cell==null) {
            return "";
        }
        Integer cellType = cell.getCellType().getCode();

        switch (cellType) {
            case 0:
                if (DateUtil.isCellDateFormatted(cell)||isDate) {
               return cell.getDateCellValue();
                } else {
                    return cell.getNumericCellValue();
                }
            case 1:
             return cell.getStringCellValue();
            case 2:
               return cell.getRichStringCellValue();
            case 4:
                return cell.getBooleanCellValue();
            case 5:
               return cell.getErrorCellValue();
            default:
               return "";
        }
    }

    /**
     * 获取指定行的指定列的值，
     * @param sheet  页
     * @param row  行
     * @param col 列
     * @return
     */
    public static  Object getValue(Sheet sheet,int row,int col,boolean isData) {
            return getValue(sheet.getRow(row).getCell(col),isData);
    }

    /**
     * 获取指定行的指定列的值，
     * @param sheet  页
     * @param row  行
     * @param col 列
     * @return
     */
    public static  Object getValue(Sheet sheet,int row,int col) {
        return getValue(sheet, row, col, false);
    }

    /**
     * 返回某一行的多个列
     * @param sheet 页
     * @param row 行
     * @param cols 多个列
     * @return
     */
    public static Map<String, Object> getValues(Sheet sheet, int row, int []cols) {
        Row row1 = sheet.getRow(row);
        Map<String, Object> map = new HashMap<>();
        for (int i=0;i<cols.length; i++) {
            Object value = getValue(row1.getCell(cols[i]));
            map.put("param"+i, value);
        }
        return map;
    }
    /**
     * 返回某一行的多个列
     * @param sheet 页
     * @param row 行
     * @param cols 多个列
     * @param key 每个的值
     * @return
     */
    public static Map<String, Object> getValues(Sheet sheet, int row, int []cols, String[] key) {
        Row row1 = sheet.getRow(row);
        Map<String, Object> map = new HashMap<>();
        for (int i=0;i<cols.length; i++) {
            Object value = getValue(row1.getCell(cols[i]));
            map.put(key[i], value);
        }
        return map;
    }


    /**
     * 通过一个sheet的指定的多个列，开始结束行，返回这些列的值
     * @param sheet 要读的页
     * @param startRow 开始行
     * @param endRow 结束行
     * @param cols 要读的列
     * @return
     */
    public static List<Map<String, Object>> getValues(Sheet sheet, int startRow, int endRow, int... cols) {
        List<Map<String, Object>> list = new ArrayList<>();
        for (int i = startRow; i <=endRow ; i++) {
            list.add(getValues(sheet, i, cols));
        }
        return list;
    }

    /**
     * 通过一个sheet的指定的多个列，开始结束行，返回这些列的值
     * @param sheet 要读的页
     * @param startRow 开始行
     * @param endRow 结束行
     * @param cols 要读的列
     * @return
     */
    public static List<Map<String, Object>> getValues(Sheet sheet, int startRow, int endRow, int[] cols,String [] keys) {
        List<Map<String, Object>> list = new ArrayList<>();
        for (int i = startRow; i <=endRow ; i++) {
            list.add(getValues(sheet, i, cols,keys));
        }
        return list;
    }


    /** 获取一共有多少行
     * */
    public static Integer getNumberOfRows(Sheet sheet) {
        return sheet.getPhysicalNumberOfRows();
    }

    /**    获取有一共多少列
     * */
    public static Integer getNumberOfCols(Row row) {
       return row.getPhysicalNumberOfCells();
    }
    static boolean b;
    /**
     * . 代表匹配除"\r\n"之外的任何单个字符  * 匹配多次===(0,)
     * .*Test.*  这个会模糊匹配  中间有Test的
     * 传入一个 页对象；和 正则表达式； 过滤出适配的;
     * @param sheet  页
     * @param value  正则表达式
     * @return 符合的合并单元格：
     */
    public static List<CellRangeAddress> getMergedRegions(Sheet sheet,String value) {
        // 输入 内容 返回 找到的单元格
       return sheet.getMergedRegions().stream().
                filter(r-> Pattern.matches(value, getValue(sheet, r.getFirstRow(), r.getFirstColumn()).toString()))
                .collect(Collectors.toList());
    }


//    测试
    public static void main(String[] args) throws IOException {






    }

}
